package com.heima.account.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baidu.aip.util.Base64Util;
import com.heima.commons.constant.HtichConstants;
import com.heima.commons.domin.bo.CardInfo;
import com.heima.commons.domin.bo.IdCardResult;
import com.heima.commons.domin.bo.LicensePlateResponse;
import com.heima.commons.domin.bo.VehicleInfo;
import com.heima.commons.enums.BusinessErrors;
import com.heima.commons.exception.BusinessRuntimeException;
import com.heima.commons.utils.GsonUtils;
import com.heima.commons.utils.HttpUtil;
import com.heima.commons.utils.RedisHelper;
import com.heima.modules.po.AuthenticationPO;
import com.heima.modules.po.VehiclePO;
import okhttp3.*;
import org.apache.commons.io.FileUtils;
import org.apache.coyote.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class AiHelper {
    @Value("${baidu.apikey}")
    private String API_KEY;
    @Value("${baidu.secretkey}")
    private String SECRET_KEY;

    private final static Logger logger = LoggerFactory.getLogger(AiHelper.class);

    final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    public static void main(String[] args) throws IOException {
        String code = new AiHelper().getLicense(null);
        System.out.println(code);
    }

    /*

    图像识别，获取车牌信息
    文档（行驶证识别）：https://cloud.baidu.com/doc/OCR/s/yk3h7y3ks
    文档（车牌识别）：https://cloud.baidu.com/doc/OCR/s/ck3h7y191
    获取车辆照片url
    将url下载到某个临时文件夹
    将文件编码为base64
    调百度AI接口，返回对应信息


    简化版业务流程（至少完成）：识别车辆车牌号即可

    * */
    public String getLicense(VehiclePO vehiclePO) throws IOException {
        //TODO:任务2.1-车辆信息验证代码编写-2day

        // 车辆照片识别
        String url1 = "https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate";
        String front = vehiclePO.getCarFrontPhoto();
        String frontPhoto = getString(vehiclePO, front, url1);
        // 得到frontPhoto中车辆车牌号码信息并封装
        LicensePlateResponse licensePlateResponse = GsonUtils.fromJson(frontPhoto, LicensePlateResponse.class);
        String carNumber = licensePlateResponse.getWords_result().getNumber();

        // 行驶证照片识别
        String url2 = "https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license";
        String carBack = vehiclePO.getCarBackPhoto();
        String carBackPhoto = getString(vehiclePO, carBack, url2);
        // 得到carBackPhoto中车辆车牌号码信息并封装
        VehicleInfo vehicleInfo = JSON.parseObject(carBackPhoto, VehicleInfo.class);
        String carBackNumber = vehicleInfo.getWords_result().get("号牌号码").getWords();

        //对比：行驶证车牌 和 车辆车牌是否一致
        //如果一致，设置车牌信息，认证通过，身份变更为车主
        if (! carNumber.equals(carBackNumber)) {
            throw new BusinessRuntimeException(BusinessErrors.PARAM_ERROR, "车辆信息不一致");
        }
        return carNumber;
    }

    private String getString(VehiclePO vehiclePO, String front, String url) throws IOException {
        String accessToken = getAccessToken();
        File tempFile = new File(AiHelper.class.getResource("/").getPath() + "front-" + vehiclePO.getId() + front.substring(front.lastIndexOf("."), front.length()));
        String imgParam = getImgParam(tempFile, front);

        String param = "image=" + imgParam;

        //调百度AI接口，返回对应信息
        // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。

        String result = null;
        try {
            result = HttpUtil.post(url, accessToken, param);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    public CardInfo getCardInfo(AuthenticationPO authenticationPO) throws Exception {
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
        String cardInfo = authenticationPO.getCardIdFrontPhoto();
        String accessToken = getAccessToken();
        File tempFile = new File(AiHelper.class.getResource("/").getPath() + "front-" + authenticationPO.getId() + cardInfo.substring(cardInfo.lastIndexOf("."), cardInfo.length()));
        String imgParam = getImgParam(tempFile, cardInfo);

        String param = "id_card_side=" + "front" + "&image=" + imgParam;

        //调百度AI接口，返回对应信息
        // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。

        String result = null;
        try {
            result = HttpUtil.post(url, accessToken, param);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        IdCardResult idCardResult = JSON.parseObject(result, IdCardResult.class);

        String name = idCardResult.getWords_result().get("姓名").getWords();
        String id = idCardResult.getWords_result().get("公民身份号码").getWords();
        String birth = idCardResult.getWords_result().get("出生").getWords();
        // birth格式化为yyyy年MM月dd日
        String formattedBirth = new SimpleDateFormat("yyyy年MM月dd日")
                .format(new SimpleDateFormat("yyyyMMdd").parse(birth));


        return new CardInfo(name, id, formattedBirth);
    }

    private static String getImgParam(File tempFile, String cardInfo) throws IOException {
        logger.info("create tempfile:{}", tempFile.getAbsolutePath());
        // 创建临时文件
        FileUtils.copyURLToFile(new URL(cardInfo), tempFile);

        byte[] imgData = FileUtils.readFileToByteArray(tempFile);
        String imgStr = Base64Util.encode(imgData);
        String imgParam = URLEncoder.encode(imgStr, "UTF-8");
        return imgParam;
    }

    public String getAccessToken() throws IOException {
        String redisAccessToken = redisTemplate.opsForValue().get(HtichConstants.ACCESS_TOKEN_KEY);
        if (redisAccessToken != null) {
            return redisAccessToken;
        }
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "");
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token?client_id=t06J9PvC8KOHwxumzux2j95n&client_secret=KcTs4DBBpWAgfuDzAyuoVMZHIYzPSMbA&grant_type=client_credentials")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject jsonObject = JSON.parseObject(response.body().string());
        String accessToken = jsonObject.getString("access_token");
        redisTemplate.opsForValue().set(HtichConstants.ACCESS_TOKEN_KEY, accessToken);
        return accessToken;
    }
}
